(function () {
    
    function Promise(excutor) {
        const _this = this;
        _this.data = undefined;
        _this.status = 'pending'
        _this.callbacks = []
        function resolve(value) {
            if (this.status != 'pending') {
                return;
            }
            _this.status = 'resolved'
            _this.data = value;
            if (_this.callbacks.length > 0) {
                _this.callbacks.forEach(item => {
                    item.onResolved(value)
                })
            }
        }

        function reject(err) {
            if (this.status != 'pending') {
                return;
            }
            _this.status = 'rejected'
            _this.data = err;
            if (_this.callbacks.length > 0) {
                _this.callbacks.forEach(item => {
                    item.onRejected(err)
                })
            }
        }
        excutor(resolve, reject)
    }

    Promise.prototype.then = function (onResolved, onRejected) {
        onResolved = typeof onResolved === 'function' ? onResolved : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : err => {
            throw err
        }
        const _this = this;
        return new Promise((resolve, reject) => {
            if (_this.status === 'pending') {
                _this.callbacks.push({
                    onResolved,
                    onRejected
                })
            } else if (_this.status === 'resolved') {
                setTimeout(function(){
                    try {
                        const result = onResolved(this.data)
                        if (result instanceof Promise) {
                            result.then(
                                value => {
                                    resolve(result)
                                },
                                err => {
                                    reject(err)
                                }
                            )
                        } else {
                            resolve(result)
                        }
                    } catch(err) {
                    throw err
                    }
                }, 0)
            } else {
                
            }
        })
    }

    Promise.prototype.catch = function (onRejected) {
        this.then(undefined, onRejected)
    }

    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(
                    response => {
                        resolve(response)
                    },
                    err => {
                        reject(err)
                    }
                )
            } else {
                resolve(value)
            }
        })
    }


    Promise.reject = function (err) {
        return new Promise((resolve, reject) => {
            reject(err)
        })
    }

    window.Promise = Promise
})(window)